; Load libraries
(use 'clojure.xml)
(use 'clojure.contrib.pprint)
(use 'clojure.contrib.zip-filter.xml)
(use 'clojure.contrib.seq-utils)
(require 
  '[clojure.zip :as zip]
  '[clojure.contrib.lazy-xml :as lxml]
  '[clojure.contrib.zip-filter :as zf]
  )

; Define input
(def file "examples/about.xml")
(def file "examples/resume_web.xml")
(def tree (parse (java.io.File. file)))
(def ztree (zip/xml-zip (parse (java.io.File. file))))
;(def xtree (zip/xml-zip (parse (java.io.File. "foo.xml"))))
;(pprint tree) 
(def x (xml-seq tree))
;(pprint x)
(println "Following unique tags in tree, you'd better have renderers for all:")
(pprint (set (for [x (xml-seq tree)] (:tag x))))


; Define runtime parameters
(def output-format :latex)

; Examples
(def small {:tag :paragraph, :attrs nil, :content ["Contact vectors include email (" {:tag :emphasis, :attrs nil, :content ["fasih dot 1 @ osu dot edu"]} ") and Facebook."]})
(def vs (nth (:content small) 1))

; Implementation
(defmulti handle_tag 
  "handle_tag is given a hashmap with keys :content, :attr, and :tag. It is a
  multimethod and its associated methods render :content depending on the :tag.
  Note that :content shall be a string. If it's a map, the rendered output will
  unexpected and incorrect, but readable."
   #(set (list (:tag %) (:output %))))
(defmethod handle_tag #{:latex :section} [tac]
  (str
    "\n\n\\section{"  
    (apply str (xml-> (zip/xml-zip tac) :title text))
    "}\n" 
    ;(apply str (filter (comp not map?) (:content tac)))))
    (apply str (filter string? (:content tac)))))
(defmethod handle_tag #{:latex :field_list} [tac]
  (str "\\begin{itemize}\n" (apply str (:content tac)) "\\end{itemize}\n"))
(defmethod handle_tag #{:latex :field} [tac] (apply str (:content tac)))
(defmethod handle_tag #{:latex :field_name} [tac]
  (str "\\item " (apply str (:content tac)) ": "))
(defmethod handle_tag #{:latex :field_body} [tac]
  (str (apply str (:content tac)) "\n"))

(defmethod handle_tag #{:latex :document} [tac]
  (str 
    "\\title{"
    (apply str (xml-> (zip/xml-zip tac) :title text))
    "}\n(" 
    (apply str (filter (comp not map?) (:content tac)))))
(defmethod handle_tag #{:latex :line_block} [tac]
  (str (apply str (:content tac))))
(defmethod handle_tag #{:latex :line} [tac]
  (str (apply str (:content tac)) "\n\n"))


(defmethod handle_tag #{:latex :bullet_list} [tac]
  (str "\\begin{itemize}\n" (apply str (:content tac)) "\\end{\\itemize}\n"))
(defmethod handle_tag #{:latex :enumerated_list} [tac]
  (str "\\begin{enumerate}\n" (apply str (:content tac)) 
    "\\end{\\enumerate}\n"))
(defmethod handle_tag #{:latex :list_item} [tac]
  (str "\n\\item " (apply str (:content tac) )))
(defmethod handle_tag #{:latex :title} [tac]
  tac)
(defmethod handle_tag #{:latex :paragraph} [tac]
  (str "\n\n" (apply str (:content tac))))
(defmethod handle_tag #{:latex :emphasis} [tac]
  (str "{\\em " (:content tac) "}"))
(defmethod handle_tag #{:latex :reference} [tac]
  (apply str (:content tac) ))
(defmethod handle_tag :default [tac]
  (str "UNKNOWN [" (:tag tac)  "], attrs: " (:attrs tac) "content: " (:content tac)))

(defn handle_tac [tree]
  "Given an xml tree, recursively stringifies all elements of the :content 
  vector, via handle_tag if needed, before sending the tree itself to 
  handle_tag for final rendering."
  (handle_tag (conj tree
    {:output output-format :content 
      (for [c (:content tree)] (if (map? c) (handle_tac c) c))})))
(defn handle_taci [tree]
  (conj tree
    {:output output-format :content ;(apply str
      (for [c (:content tree)] (if (map? c) (handle_tac c) c))}))

; Examples
;(xml-> ztree :section :section :title text)

;(println (handle_tac tree))
(def sec (conj (nth (filter map? (:content tree)) 2) {:output :latex}))
(println (handle_tac tree))

